﻿using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Volo.Abp.Application.Services;
using System.Threading;

namespace NewRetail.Application.Utility
{
    public interface IHttpHelperService : IApplicationService
    {
        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        string Get(string uri);
        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        Task<string> GetAsync(string uri);

        /// <summary>
        /// get1
        /// </summary>
        /// <param name="requestUri"></param>
        /// <param name="parameters"></param>
        /// <param name="token"></param>
        /// <param name="needGZip"></param>
        /// <returns></returns>
        string Get1(string requestUri, Dictionary<string, string> parameters, string token, bool needGZip = false);
        Task<string> Get2(string requestUri);

        /// <summary>
        /// Post请求
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="json"></param>
        /// <param name="mediaType"></param>
        /// <returns></returns>
        string Post(string uri, string json, string mediaType = "application/json");

        /// <summary>
        ///  Post请求(byte[])
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="postData">请求接口的数据</param>
        /// <returns></returns>
        Task<string> PostAsync(string uri, byte[] postData);
        /// <summary>
        ///  Post请求
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="json">请求接口的body数据</param>
        /// <param name="isAddHeader">header中是否需要添加参数，true要添加，false不需要添加</param>
        /// <param name="token">请求接口时候header中需要添加的token值，只有isAddHeader为true时才有效</param>
        /// <returns>（接口返回的json字符串，自定义返回的值）</returns>
        Task<string> PostDfAsync(string uri, string json, bool isAddHeader, string token, CancellationToken cancellationToken = default(CancellationToken));

        /// <summary>
        ///  异步Post请求微信V3
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="json">请求接口的body数据</param>
        /// <param name="isAddHeader">header中是否需要添加参数，true要添加，false不需要添加</param>
        /// <param name="headAuthorizationValue">只有isAddHeader为true时才有效</param>
        /// <returns>（接口返回的json字符串，自定义返回的值）</returns>
        Task<string> PostWxV3Async(string uri, string json, bool isAddHeader, string headAuthorizationValue);
    }

    public class HttpHelperService : ApplicationService, IHttpHelperService
    {
        #region 变量

        //静态对象
        private readonly IHttpClientFactory _httpClientFactory;

        #endregion

        #region 构造函数
        public HttpHelperService(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
        #endregion

        #region method

        #region Get请求
        /// <summary>
        /// Get请求
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public string Get(string uri)
        {
            return _httpClientFactory.CreateClient().GetStringAsync(uri).Result;
        }
        #endregion

        #region Get异步请求
        /// <summary>
        /// Get异步请求
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public async Task<string> GetAsync(string uri)
        {
            var result = await _httpClientFactory.CreateClient().GetStringAsync(uri);
            return result;
        }
        #endregion

        #region get1
        public string Get1(string requestUri, Dictionary<string, string> parameters, string token, bool needGZip = false)
        {
            //从工厂获取请求对象
            var client = _httpClientFactory.CreateClient();
            //添加请求头
            if (!string.IsNullOrWhiteSpace(token))
            {
                client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            }
            client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
            //拼接地址
            if (parameters != null)
            {
                var strParam = string.Join("&", parameters.Select(o => o.Key + "=" + o.Value));
                requestUri = string.Concat(requestUri, '?', strParam);
            }
            client.BaseAddress = new Uri(requestUri);
            string result = "";
            if (needGZip)
            {
                using (var stream = client.GetStreamAsync(requestUri).Result)
                using (var decompressed = new GZipStream(stream, CompressionMode.Decompress))
                using (StreamReader reader = new StreamReader(decompressed))
                {
                    result = reader.ReadToEnd();
                }
                return result;
            }
            else
            {
                return client.GetStringAsync(requestUri).Result;
            }
        }
        #endregion

        #region get1
        public async Task<string> Get2(string requestUri)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
            request.Headers.Add("Accept", "application/vnd.github.v3+json");
            request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

            var handler = new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip
            };

            var client = _httpClientFactory.CreateClient();

            var response = await client.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                var responseStream = await response.Content.ReadAsStringAsync();
                //var ret = await System.Text.Json.JsonSerializer.DeserializeAsync<string>(responseStream);
                //var ret = JsonConvert.DeserializeObject<string>(responseStream);
                return responseStream;
            }
            else
            {
                return null;
            }
        }
        #endregion

        #region Post
        /// <summary>
        /// Post请求
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="json"></param>
        /// <param name="mediaType"></param>
        /// <returns></returns>
        public string Post(string uri, string json, string mediaType = "application/json")
        {
            HttpResponseMessage message = null;
            string result = null;

            HttpContent httpContent = new StringContent(json, System.Text.Encoding.UTF8, mediaType);

            message = _httpClientFactory.CreateClient().PostAsync(uri, httpContent).Result;

            if (message.IsSuccessStatusCode)
            {
                result = message.Content.ReadAsStringAsync().Result;
            }

            return result;
        }
        #endregion        

        #region 异步Post请求
        /// <summary>
        ///  Post请求
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="json">请求接口的body数据</param>
        /// <param name="isAddHeader">header中是否需要添加参数，true要添加，false不需要添加</param>
        /// <param name="token">请求接口时候header中需要添加的token值，只有isAddHeader为true时才有效</param>
        /// <returns>（接口返回的json字符串，自定义返回的值）</returns>
        public async Task<string> PostDfAsync(string uri, string json, bool isAddHeader, string token, CancellationToken cancellationToken = default(CancellationToken))
        {
            var ctsForTimeout = new CancellationTokenSource();
            ctsForTimeout.CancelAfter(TimeSpan.FromSeconds(30));
            var cancellationTokenForTimeout = ctsForTimeout.Token;

            HttpResponseMessage message = null;
            HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, uri);
            msg.Content = new StringContent(json, Encoding.UTF8, "application/json");
            if (isAddHeader)
            {
                msg.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
                msg.Headers.Add("token", token);
                msg.Headers.Add("timestamp", UtilsHelper.getFormatedDateString("China Standard Time"));
            }
            using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancellationTokenForTimeout))
            {
                try
                {
                    message = await _httpClientFactory.CreateClient().SendAsync(msg, linkedCts.Token);
                    if (!message.IsSuccessStatusCode)
                    {
                        return "";
                    }
                    return message.Content.ReadAsStringAsync().Result;
                }
                catch (Exception ex)
                {
                    //just for illustration purposes
                    if (cancellationTokenForTimeout.IsCancellationRequested)
                    {
                        Console.WriteLine("timeout");
                    }
                    else if (cancellationToken.IsCancellationRequested)
                    {
                        Console.WriteLine("other cancellation token cancelled");
                    }
                    throw;
                }

            }
            //message = await _httpClientFactory.CreateClient().SendAsync(msg);
            //return message.Content.ReadAsStringAsync().Result;

        }
        #endregion       

        #region Post请求(byte[])
        /// <summary>
        ///  Post请求(byte[])
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="postData">请求接口的数据</param>
        /// <returns></returns>
        public async Task<string> PostAsync(string uri, byte[] postData)
        {
            HttpResponseMessage message = null;
            HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, uri);
            //msg.Content = new ByteArrayContent(postData, 0, postData.Length);
            msg.Content = new StringContent(Encoding.Default.GetString(postData), Encoding.UTF8, "application/octet-stream");
            
            message = await _httpClientFactory.CreateClient().SendAsync(msg);
            return message.Content.ReadAsStringAsync().Result;

        }
        #endregion

        #region 异步Post请求微信V3
        /// <summary>
        ///  异步Post请求微信V3
        /// </summary>
        /// <param name="uri">请求接口地址</param>
        /// <param name="json">请求接口的body数据</param>
        /// <param name="isAddHeader">header中是否需要添加参数，true要添加，false不需要添加</param>
        /// <param name="headAuthorizationValue">只有isAddHeader为true时才有效</param>
        /// <returns>（接口返回的json字符串，自定义返回的值）</returns>
        public async Task<string> PostWxV3Async(string uri, string json, bool isAddHeader, string headAuthorizationValue)
        {
            HttpResponseMessage message = null;
            HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, uri);
            msg.Content = new StringContent(json, Encoding.UTF8, "application/json");
            if (isAddHeader)
            {
                msg.Headers.Add("Authorization", headAuthorizationValue);
                msg.Headers.Add("Accept", "application/json");
                msg.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
            }
            message = await _httpClientFactory.CreateClient().SendAsync(msg);
            return message.Content.ReadAsStringAsync().Result;

        }
        #endregion

        #endregion
    }
}
